class YOLOv9Backbone(BaseBackbone):
    # From left to right:
    arch_settings = {
        'P5': [
            # Format: [in_channels, out_channels, c3, c4, num_blocks, is_last]
            # --------------------------------------------
            # Stage 1: RepNCSPELAN4(128→256) → ADown(256)
            [128, 256, 128, 64, 1, False],
            
            # Stage 2: RepNCSPELAN4(256→512) → ADown(512)
            [256, 512, 256, 128, 1, False],
            
            # Stage 3: RepNCSPELAN4(512→512) → ADown(512)
            [512, 512, 512, 256, 1, False],
            
            # Stage 4: RepNCSPELAN4(512→512) → No ADown
            [512, 512, 512, 256, 1, True]
        ]
    }

    def __init__(self, 
                 arch: str = 'P5',
                 last_stage_out_channels: int = 1024,
                 plugins: Union[dict, List[dict]] = None,
                 deepen_factor: float = 1.0,
                 widen_factor: float = 1.0,
                 input_channels: int = 3,
                 out_indices: Tuple[int] = (2, 3, 4),
                 frozen_stages: int = -1,
                 norm_cfg: ConfigType = dict(
                     type='BN', momentum=0.03, eps=0.001),
                 act_cfg: ConfigType = dict(type='SiLU', inplace=True),
                 norm_eval: bool = False,
                 init_cfg: OptMultiConfig = None):
        self.arch_settings[arch][-1][1] = last_stage_out_channels
        super().__init__(
            self.arch_settings[arch],
            deepen_factor,
            widen_factor,
            input_channels=input_channels,
            out_indices=out_indices,
            plugins=plugins,
            frozen_stages=frozen_stages,
            norm_cfg=norm_cfg,
            act_cfg=act_cfg,
            norm_eval=norm_eval,
            init_cfg=init_cfg)

    def build_stem_layer(self):
        """Build YOLOv9-compliant stem layer with Silence and Conv layers."""
        stem = nn.Sequential(
            # Silence Layer (Layer 0)
            Silence(),  # Essential for YOLOv9's input preprocessing
            
            # First Conv (Layer 1: 3 -> 64)
            ConvModule(
                self.input_channels,
                make_divisible(64, self.widen_factor),  # arch_setting[0][0] = 64
                kernel_size=3,
                stride=2,
                padding=1,
                norm_cfg=self.norm_cfg,
                act_cfg=self.act_cfg),
            
            # Second Conv (Layer 2: 64 -> 128)
            ConvModule(
                make_divisible(64, self.widen_factor),  # Input from previous layer
                make_divisible(128, self.widen_factor),  # arch_setting[0][1] = 128
                kernel_size=3,
                stride=2,
                padding=1,
                norm_cfg=self.norm_cfg,
                act_cfg=self.act_cfg)
        )
        return stem
    
    def build_stage_layer(self, stage_idx: int, setting: list):
        """Build a stage layer.

        Args:
            stage_idx (int): The index of a stage layer.
            setting (list): The architecture setting of a stage layer.
        """
        in_channels, out_channels, c3, c4, num_blocks, is_last = setting  # Updated

        in_channels = make_divisible(in_channels, self.widen_factor)
        out_channels = make_divisible(out_channels, self.widen_factor)
        c3 = make_divisible(c3, self.widen_factor)
        c4 = make_divisible(c4, self.widen_factor)
        num_blocks = make_round(num_blocks, self.deepen_factor)

        # stage = []
        stage = nn.Sequential()
        # RepNCSPELAN4 (Channel Processing)
        rep4_layer = RepNCSPELAN4(
            c1=in_channels,
            c2=out_channels,  # Output = YAML-defined value
            c3=c3,
            c4=c4,
            c5=num_blocks
        )
        stage.append(rep4_layer)
        if not is_last :
            adown_layer = ADown(
                out_channels, 
                out_channels)
            stage.append(adown_layer)

        return stage